/**
 * - 作者: DoooReyn
 * - 日期: 2023.10.29
 * - 名称: Numbers
 * - 描述: 数值辅助工具
 */
export class Numbers {
    /**
     * 向下取整
     * @param n 数值
     * @returns
     */
    static floor(n: number) {
        if (n >= 2147483648 || n <= -2147483648) return Math.floor(n);
        return n | 0;
    }

    /**
     * 向上取整
     * @param n 数值
     * @returns
     */
    static ceil(n: number) {
        const nn = Numbers.floor(n);
        return nn + (n > nn ? 1 : 0);
    }

    /**
     * 获取数值的整数部分
     * @param n 数值
     * @returns
     */
    static toDecimal(n: number) {
        return this.floor(n | 0);
    }

    /**
     * 获取数值的小数部分
     * @param n 数值
     * @returns
     */
    static toFraction(n: number) {
        return n - this.toDecimal(n);
    }

    /**
     * 保留数值的小数点后几位
     * @param n 数值
     * @param count 位数
     * @returns
     */
    static toFractionAfter(n: number, count: number) {
        count = Math.max(0, count | 0);
        const ret = Math.pow(10, count);
        return this.floor(n * ret) / ret;
    }

    /**
     * 比较两个数值是否近似相等
     * @param 数值 a
     * @param 数值 b
     * @returns
     */
    static equalApproximately(a: number, b: number): boolean {
        return this.floor(Math.abs(a - b) * 1e6) <= 1;
    }

    /**
     * 截取数值到指定范围
     * @param n 数值
     * @param min 限定最小值
     * @param max 限定最大值
     * @returns
     */
    static clamp(n: number, min: number, max: number): number {
        return Math.min(Math.max(n, min), max);
    }

    /**
     * 数值是否位于限定范围内
     * @param v 数值
     * @param min 限定最小值
     * @param max 限定最大值
     * @returns
     */
    static isInRange(v: number, min: number, max: number) {
        return v >= min && v <= max;
    }

    /**
     * 转换为整数
     * @param value 输入数值
     * @param defaultValue 默认数值
     */
    static toInteger(value: any, defaultValue: number) {
        const ret = parseInt(value);
        return isNaN(ret) ? this.floor(defaultValue) : ret;
    }

    /**
     * 转换为浮点数
     * @param value 输入数值
     * @param defaultValue 默认数值
     * @returns
     */
    static toFloat(value: any, defaultValue: number) {
        const ret = parseFloat(value);
        return isNaN(ret) ? defaultValue : ret;
    }
}
